dhcpv6: create struct dhcpv6_lease
authorDavid Härdeman <[email protected]>
Thu, 9 Oct 2025 05:26:00 +0000 (07:26 +0200)
committerÁlvaro Fernández Rojas <[email protected]>
Tue, 4 Nov 2025 07:51:20 +0000 (08:51 +0100)
This concludes the lease/assignment struct saga. "struct dhcp_assignment" is
converted to "struct dhcpv6_lease" and various function names, etc are updated.

I intentionally did *not* change variable names here to keep the patch as
simple as possible. Therefore, the DHCPv6 codebase is still full of lots of
variables named things like "a". I expect that to change over time when I
tackle DHCPv6 code in ernest. But it'll have to do for now.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/292
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
src/config.c
src/dhcpv6-ia.c
src/odhcpd.h
src/ubus.c

index c424266c6b4a396e15bcef4e993f5f483832d866..63e3952f666d6924d3c85641fee56fc56bca0b52 100644 (file)
@@ -708,7 +708,7 @@ int config_set_lease_cfg_from_blobmsg(struct blob_attr *ba)
                lease_cfg->leasetime = time;
        }
 
-       INIT_LIST_HEAD(&lease_cfg->assignments);
+       INIT_LIST_HEAD(&lease_cfg->dhcpv6_leases);
        vlist_add(&lease_cfgs, &lease_cfg->node, lease_cfg);
        return 0;
 
@@ -1744,18 +1744,18 @@ static int set_interface(struct uci_section *s)
        return config_parse_interface(blob_data(b.head), blob_len(b.head), s->e.name, true);
 }
 
-static void lease_cfg_delete_dhcpv6_assignments(struct lease_cfg *lease_cfg)
+static void lease_cfg_delete_dhcpv6_leases(struct lease_cfg *lease_cfg)
 {
-       struct dhcp_assignment *a, *tmp;
+       struct dhcpv6_lease *lease, *tmp;
 
-       list_for_each_entry_safe(a, tmp, &lease_cfg->assignments, lease_cfg_list)
-               free_assignment(a);
+       list_for_each_entry_safe(lease, tmp, &lease_cfg->dhcpv6_leases, lease_cfg_list)
+               dhcpv6_free_lease(lease);
 }
 
-static void lease_cfg_update_assignments(struct lease_cfg *lease_cfg)
+static void lease_cfg_update_leases(struct lease_cfg *lease_cfg)
 {
        struct dhcpv4_lease *a4 = lease_cfg->dhcpv4_lease;
-       struct dhcp_assignment *a;
+       struct dhcpv6_lease *lease6;
 
        if (a4) {
                free(a4->hostname);
@@ -1765,14 +1765,14 @@ static void lease_cfg_update_assignments(struct lease_cfg *lease_cfg)
                        a4->hostname = strdup(lease_cfg->hostname);
        }
 
-       list_for_each_entry(a, &lease_cfg->assignments, lease_cfg_list) {
-               free(a->hostname);
-               a->hostname = NULL;
+       list_for_each_entry(lease6, &lease_cfg->dhcpv6_leases, lease_cfg_list) {
+               free(lease6->hostname);
+               lease6->hostname = NULL;
 
                if (lease_cfg->hostname)
-                       a->hostname = strdup(lease_cfg->hostname);
+                       lease6->hostname = strdup(lease_cfg->hostname);
 
-               a->leasetime = lease_cfg->leasetime;
+               lease6->leasetime = lease_cfg->leasetime;
        }
 }
 
@@ -1837,11 +1837,11 @@ static void lease_cfg_change(struct lease_cfg *lease_cfg_old, struct lease_cfg *
 
        if (lease_cfg_old->hostid != lease_cfg_new->hostid) {
                lease_cfg_old->hostid = lease_cfg_new->hostid;
-               lease_cfg_delete_dhcpv6_assignments(lease_cfg_old);
+               lease_cfg_delete_dhcpv6_leases(lease_cfg_old);
        }
 
        if (update)
-               lease_cfg_update_assignments(lease_cfg_old);
+               lease_cfg_update_leases(lease_cfg_old);
 
        free_lease_cfg(lease_cfg_new);
 }
@@ -1849,7 +1849,7 @@ static void lease_cfg_change(struct lease_cfg *lease_cfg_old, struct lease_cfg *
 static void lease_cfg_delete(struct lease_cfg *lease_cfg)
 {
        dhcpv4_free_lease(lease_cfg->dhcpv4_lease);
-       lease_cfg_delete_dhcpv6_assignments(lease_cfg);
+       lease_cfg_delete_dhcpv6_leases(lease_cfg);
        free_lease_cfg(lease_cfg);
 }
 
index 3046606898c6740a00cd0aeb8994899696718ae3..a7af7d057f0ec3bdb367721890a7fc35a9698c64 100644 (file)
      (addrs)[(i)].prefix > 64)
 
 static void dhcpv6_netevent_cb(unsigned long event, struct netevent_handler_info *info);
-static void apply_lease(struct dhcp_assignment *a, bool add);
-static void set_border_assignment_size(struct interface *iface, struct dhcp_assignment *b);
+static void apply_lease(struct dhcpv6_lease *a, bool add);
+static void set_border_assignment_size(struct interface *iface, struct dhcpv6_lease *b);
 static void handle_addrlist_change(struct netevent_handler_info *info);
-static void start_reconf(struct dhcp_assignment *a);
-static void stop_reconf(struct dhcp_assignment *a);
+static void start_reconf(struct dhcpv6_lease *a);
+static void stop_reconf(struct dhcpv6_lease *a);
 static void valid_until_cb(struct uloop_timeout *event);
 
 static struct netevent_handler dhcpv6_netevent_handler = { .cb = dhcpv6_netevent_cb, };
@@ -53,6 +53,41 @@ static struct uloop_timeout valid_until_timeout = {.cb = valid_until_cb};
 static uint32_t serial = 0;
 static uint8_t statemd5[16];
 
+static struct dhcpv6_lease *
+dhcpv6_alloc_lease(size_t extra_len)
+{
+       struct dhcpv6_lease *a = calloc(1, sizeof(*a) + extra_len);
+
+       if (!a)
+               return NULL;
+
+       INIT_LIST_HEAD(&a->head);
+       INIT_LIST_HEAD(&a->lease_cfg_list);
+
+       return a;
+}
+
+void dhcpv6_free_lease(struct dhcpv6_lease *a)
+{
+       list_del(&a->head);
+       list_del(&a->lease_cfg_list);
+
+       if (a->managed_sock.fd.registered) {
+               ustream_free(&a->managed_sock.stream);
+               close(a->managed_sock.fd.fd);
+       }
+
+       if ((a->flags & OAF_BOUND) && (a->flags & OAF_DHCPV6_PD))
+               apply_lease(a, false);
+
+       if (a->fr_cnt)
+               stop_reconf(a);
+
+       free(a->managed);
+       free(a->hostname);
+       free(a);
+}
+
 int dhcpv6_ia_init(void)
 {
        uloop_timeout_set(&valid_until_timeout, 1000);
@@ -67,10 +102,10 @@ int dhcpv6_ia_setup_interface(struct interface *iface, bool enable)
        enable = enable && (iface->dhcpv6 == MODE_SERVER);
 
        if (enable) {
-               struct dhcp_assignment *border;
+               struct dhcpv6_lease *border;
 
                if (list_empty(&iface->ia_assignments)) {
-                       border = alloc_assignment(0);
+                       border = dhcpv6_alloc_lease(0);
 
                        if (!border) {
                                warn("Failed to alloc border on %s", iface->name);
@@ -80,15 +115,15 @@ int dhcpv6_ia_setup_interface(struct interface *iface, bool enable)
                        border->length = 64;
                        list_add(&border->head, &iface->ia_assignments);
                } else
-                       border = list_last_entry(&iface->ia_assignments, struct dhcp_assignment, head);
+                       border = list_last_entry(&iface->ia_assignments, struct dhcpv6_lease, head);
 
                set_border_assignment_size(iface, border);
        } else {
-               struct dhcp_assignment *c;
+               struct dhcpv6_lease *c;
 
                while (!list_empty(&iface->ia_assignments)) {
-                       c = list_first_entry(&iface->ia_assignments, struct dhcp_assignment, head);
-                       free_assignment(c);
+                       c = list_first_entry(&iface->ia_assignments, struct dhcpv6_lease, head);
+                       dhcpv6_free_lease(c);
                }
        }
 
@@ -113,7 +148,7 @@ static void dhcpv6_netevent_cb(unsigned long event, struct netevent_handler_info
 }
 
 
-static inline bool valid_prefix_length(const struct dhcp_assignment *a, const uint8_t prefix_length)
+static inline bool valid_prefix_length(const struct dhcpv6_lease *a, const uint8_t prefix_length)
 {
        return (a->managed_size || a->length > prefix_length);
 }
@@ -146,7 +181,7 @@ enum {
        IOV_TOTAL
 };
 
-static int send_reconf(struct dhcp_assignment *assign)
+static int send_reconf(struct dhcpv6_lease *assign)
 {
        struct interface *iface = assign->iface;
        struct dhcpv6_client_header hdr = {
@@ -203,7 +238,7 @@ static int send_reconf(struct dhcp_assignment *assign)
 
        memcpy(clientid.data, assign->clid_data, assign->clid_len);
 
-       struct iovec iov[IOV_MAX] = {
+       struct iovec iov[IOV_TOTAL] = {
                [IOV_HDR] = { &hdr, sizeof(hdr) },
                [IOV_SERVERID] = { &serverid, sizeof(serverid) },
                [IOV_CLIENTID] = { &clientid, sizeof(clientid) },
@@ -238,22 +273,6 @@ static int send_reconf(struct dhcp_assignment *assign)
        return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, iov, ARRAY_SIZE(iov), iface);
 }
 
-static void dhcpv6_ia_free_assignment(struct dhcp_assignment *a)
-{
-       if (a->managed_sock.fd.registered) {
-               ustream_free(&a->managed_sock.stream);
-               close(a->managed_sock.fd.fd);
-       }
-
-       if ((a->flags & OAF_BOUND) && (a->flags & OAF_DHCPV6_PD))
-               apply_lease(a, false);
-
-       if (a->fr_cnt)
-               stop_reconf(a);
-
-       free(a->managed);
-}
-
 static void in6_copy_iid(struct in6_addr *dest, uint64_t iid, unsigned n)
 {
        uint64_t iid_be = htobe64(iid);
@@ -286,7 +305,7 @@ static struct in6_addr in6_from_prefix_and_iid(const struct odhcpd_ipaddr *prefi
        return addr;
 }
 
-void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcp_assignment *c,
+void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcpv6_lease *c,
                          time_t now, dhcpv6_binding_cb_handler_t func, void *arg)
 {
        struct odhcpd_ipaddr *addrs = (c->managed) ? c->managed : iface->addr6;
@@ -348,7 +367,7 @@ void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcp_assignment *c,
 struct write_ctxt {
        FILE *fp;
        md5_ctx_t md5;
-       struct dhcp_assignment *c;
+       struct dhcpv6_lease *c;
        struct interface *iface;
        char *buf;
        int buf_len;
@@ -655,7 +674,7 @@ void dhcpv6_ia_write_statefile(void)
        }
 }
 
-static void __apply_lease(struct dhcp_assignment *a,
+static void __apply_lease(struct dhcpv6_lease *a,
                struct odhcpd_ipaddr *addrs, ssize_t addr_len, bool add)
 {
        if (a->flags & OAF_DHCPV6_NA)
@@ -675,7 +694,7 @@ static void __apply_lease(struct dhcp_assignment *a,
        }
 }
 
-static void apply_lease(struct dhcp_assignment *a, bool add)
+static void apply_lease(struct dhcpv6_lease *a, bool add)
 {
        struct interface *iface = a->iface;
        struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6;
@@ -685,7 +704,7 @@ static void apply_lease(struct dhcp_assignment *a, bool add)
 }
 
 /* Set border assignment size based on the IPv6 address prefixes */
-static void set_border_assignment_size(struct interface *iface, struct dhcp_assignment *b)
+static void set_border_assignment_size(struct interface *iface, struct dhcpv6_lease *b)
 {
        time_t now = odhcpd_time();
        int minprefix = -1;
@@ -712,7 +731,7 @@ static void set_border_assignment_size(struct interface *iface, struct dhcp_assi
 static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new)
 {
        struct ustream_fd *fd = container_of(s, struct ustream_fd, stream);
-       struct dhcp_assignment *c = container_of(fd, struct dhcp_assignment, managed_sock);
+       struct dhcpv6_lease *c = container_of(fd, struct dhcpv6_lease, managed_sock);
        time_t now = odhcpd_time();
        bool first = c->managed_size < 0;
 
@@ -776,7 +795,7 @@ static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new)
        }
 
        if (first && c->managed_size == 0)
-               free_assignment(c);
+               dhcpv6_free_lease(c);
        else if (first)
                c->valid_until = now + 150;
 }
@@ -786,7 +805,7 @@ static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new)
 static void managed_handle_pd_done(struct ustream *s)
 {
        struct ustream_fd *fd = container_of(s, struct ustream_fd, stream);
-       struct dhcp_assignment *c = container_of(fd, struct dhcp_assignment, managed_sock);
+       struct dhcpv6_lease *c = container_of(fd, struct dhcpv6_lease, managed_sock);
 
        c->valid_until = odhcpd_time() + 15;
 
@@ -796,9 +815,9 @@ static void managed_handle_pd_done(struct ustream *s)
                c->fr_cnt = 1;
 }
 
-static bool assign_pd(struct interface *iface, struct dhcp_assignment *assign)
+static bool assign_pd(struct interface *iface, struct dhcpv6_lease *assign)
 {
-       struct dhcp_assignment *c;
+       struct dhcpv6_lease *c;
 
        if (iface->dhcpv6_pd_manager[0]) {
                int fd = usock(USOCK_UNIX | USOCK_TCP, iface->dhcpv6_pd_manager, NULL);
@@ -901,9 +920,9 @@ static bool is_reserved_ipv6_iid(uint64_t iid)
        return false;
 }
 
-static bool assign_na(struct interface *iface, struct dhcp_assignment *a)
+static bool assign_na(struct interface *iface, struct dhcpv6_lease *a)
 {
-       struct dhcp_assignment *c;
+       struct dhcpv6_lease *c;
        uint64_t pool_start = 0x100;
        uint64_t pool_end = (iface->dhcpv6_hostid_len >= 64) ? UINT64_MAX : ((1ULL << iface->dhcpv6_hostid_len) - 1);
        uint64_t pool_size = pool_end - pool_start + 1;
@@ -955,8 +974,8 @@ static bool assign_na(struct interface *iface, struct dhcp_assignment *a)
 static void handle_addrlist_change(struct netevent_handler_info *info)
 {
        struct interface *iface = info->iface;
-       struct dhcp_assignment *c, *d, *border = list_last_entry(
-                       &iface->ia_assignments, struct dhcp_assignment, head);
+       struct dhcpv6_lease *c, *d, *border = list_last_entry(
+                       &iface->ia_assignments, struct dhcpv6_lease, head);
        struct list_head reassign = LIST_HEAD_INIT(reassign);
        time_t now = odhcpd_time();
 
@@ -982,7 +1001,7 @@ static void handle_addrlist_change(struct netevent_handler_info *info)
                        apply_lease(c, true);
 
                if (c->accept_fr_nonce && c->fr_cnt == 0) {
-                       struct dhcp_assignment *a;
+                       struct dhcpv6_lease *a;
 
                        start_reconf(c);
 
@@ -995,10 +1014,10 @@ static void handle_addrlist_change(struct netevent_handler_info *info)
        }
 
        while (!list_empty(&reassign)) {
-               c = list_first_entry(&reassign, struct dhcp_assignment, head);
+               c = list_first_entry(&reassign, struct dhcpv6_lease, head);
                list_del_init(&c->head);
                if (!assign_pd(iface, c))
-                       free_assignment(c);
+                       dhcpv6_free_lease(c);
        }
 
        dhcpv6_ia_write_statefile();
@@ -1006,7 +1025,7 @@ static void handle_addrlist_change(struct netevent_handler_info *info)
 
 static void reconf_timeout_cb(struct uloop_timeout *event)
 {
-       struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, fr_timer);
+       struct dhcpv6_lease *a = container_of(event, struct dhcpv6_lease, fr_timer);
 
        if (a->fr_cnt > 0 && a->fr_cnt < DHCPV6_REC_MAX_RC) {
                send_reconf(a);
@@ -1017,7 +1036,7 @@ static void reconf_timeout_cb(struct uloop_timeout *event)
                stop_reconf(a);
 }
 
-static void start_reconf(struct dhcp_assignment *a)
+static void start_reconf(struct dhcpv6_lease *a)
 {
        uloop_timeout_set(&a->fr_timer,
                          DHCPV6_REC_TIMEOUT << a->fr_cnt);
@@ -1027,7 +1046,7 @@ static void start_reconf(struct dhcp_assignment *a)
        send_reconf(a);
 }
 
-static void stop_reconf(struct dhcp_assignment *a)
+static void stop_reconf(struct dhcpv6_lease *a)
 {
        uloop_timeout_cancel(&a->fr_timer);
        a->fr_cnt = 0;
@@ -1040,21 +1059,21 @@ static void valid_until_cb(struct uloop_timeout *event)
        time_t now = odhcpd_time();
 
        avl_for_each_element(&interfaces, iface, avl) {
-               struct dhcp_assignment *a, *n;
+               struct dhcpv6_lease *a, *n;
 
                if (iface->dhcpv6 != MODE_SERVER)
                        continue;
 
                list_for_each_entry_safe(a, n, &iface->ia_assignments, head) {
                        if (a->clid_len > 0 && !INFINITE_VALID(a->valid_until) && a->valid_until < now)
-                               free_assignment(a);
+                               dhcpv6_free_lease(a);
                }
        }
        uloop_timeout_set(event, 1000);
 }
 
 static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status,
-               const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a,
+               const struct dhcpv6_ia_hdr *ia, struct dhcpv6_lease *a,
                struct interface *iface, bool request)
 {
        struct dhcpv6_ia_hdr o_ia = {
@@ -1329,7 +1348,7 @@ static void dhcpv6_log_ia_addr(struct in6_addr *addr, int prefix, _unused uint32
 }
 
 static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now,
-               const char *duidbuf, bool is_pd, struct dhcp_assignment *a, int code)
+               const char *duidbuf, bool is_pd, struct dhcpv6_lease *a, int code)
 {
        const char *type = "UNKNOWN";
        const char *status = "UNKNOWN";
@@ -1390,7 +1409,7 @@ static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now,
             duidbuf, iface->name, status, leasebuf);
 }
 
-static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a,
+static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcpv6_lease *a,
                struct interface *iface)
 {
        struct odhcpd_ipaddr *addrs = (a && a->managed) ? a->managed : iface->addr6;
@@ -1437,7 +1456,7 @@ static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcp_assign
 ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *iface,
                const struct sockaddr_in6 *addr, const void *data, const uint8_t *end)
 {
-       struct dhcp_assignment *first = NULL;
+       struct dhcpv6_lease *first = NULL;
        const struct dhcpv6_client_header *hdr = data;
        time_t now = odhcpd_time();
        uint16_t otype, olen, clid_len = 0;
@@ -1548,7 +1567,7 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac
                }
 
                /* Find an existing assignment */
-               struct dhcp_assignment *c, *a = NULL;
+               struct dhcpv6_lease *c, *a = NULL;
                list_for_each_entry(c, &iface->ia_assignments, head) {
                        /* If we're looking for a PD, is this a PD? */
                        if (is_pd && !(c->flags & OAF_DHCPV6_PD))
@@ -1598,7 +1617,7 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac
                                         * already knows or doesn't care about the old assignment.
                                         */
                                        stop_reconf(c);
-                                       free_assignment(c);
+                                       dhcpv6_free_lease(c);
                                        goto proceed;
                                }
                                continue;
@@ -1616,7 +1635,7 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac
                }
 
                if (lease_cfg && a && a->lease_cfg != lease_cfg) {
-                       free_assignment(a);
+                       dhcpv6_free_lease(a);
                        a = NULL;
                }
 
@@ -1635,7 +1654,7 @@ proceed:
                                if ((!iface->no_dynamic_dhcp || (lease_cfg && is_na)) &&
                                    (iface->dhcpv6_pd || iface->dhcpv6_na)) {
                                        /* Create new binding */
-                                       a = alloc_assignment(clid_len);
+                                       a = dhcpv6_alloc_lease(clid_len);
 
                                        if (a) {
                                                a->clid_len = clid_len;
@@ -1649,7 +1668,6 @@ proceed:
                                                        a->assigned_subnet_id = reqhint;
                                                a->valid_until =  now;
                                                a->preferred_until =  now;
-                                               a->dhcp_free_cb = dhcpv6_ia_free_assignment;
                                                a->iface = iface;
                                                a->flags = (is_pd ? OAF_DHCPV6_PD : OAF_DHCPV6_NA);
 
@@ -1673,7 +1691,7 @@ proceed:
                                                        if (lease_cfg->leasetime)
                                                                a->leasetime = lease_cfg->leasetime;
 
-                                                       list_add(&a->lease_cfg_list, &lease_cfg->assignments);
+                                                       list_add(&a->lease_cfg_list, &lease_cfg->dhcpv6_leases);
                                                        a->lease_cfg = lease_cfg;
                                                }
 
@@ -1753,7 +1771,7 @@ proceed:
                                apply_lease(a, true);
                        } else if (!assigned && a && a->managed_size == 0) {
                                /* Cleanup failed assignment */
-                               free_assignment(a);
+                               dhcpv6_free_lease(a);
                                a = NULL;
                        }
                } else if (hdr->msg_type == DHCPV6_MSG_RENEW ||
index 395cee530e29b7b80c4fc174fb61896769f9fd82..41c0099116f29bee5447c4de31d8f3473ac33fa8 100644 (file)
@@ -251,27 +251,10 @@ struct dhcpv4_lease {
        struct odhcpd_ref_ip *fr_ip;            // FR message old serverid/IP
 };
 
-/* This corresponds to a UCI host section, i.e. a static lease cfg */
-struct lease_cfg {
-       struct vlist_node node;
-       struct list_head assignments;
-       struct dhcpv4_lease *dhcpv4_lease;
-       uint32_t ipaddr;
-       uint64_t hostid;
-       size_t mac_count;
-       struct ether_addr *macs;
-       size_t duid_count;
-       struct duid *duids;
-       uint32_t leasetime;             // duration of granted leases, UINT32_MAX = inf
-       char *hostname;
-};
-
-struct dhcp_assignment {
+struct dhcpv6_lease {
        struct list_head head;
        struct list_head lease_cfg_list;
 
-       void (*dhcp_free_cb)(struct dhcp_assignment *a);
-
        struct interface *iface;
        struct lease_cfg *lease_cfg;
 
@@ -304,6 +287,21 @@ struct dhcp_assignment {
        uint8_t clid_data[];
 };
 
+/* This corresponds to a UCI host section, i.e. a static lease cfg */
+struct lease_cfg {
+       struct vlist_node node;
+       struct list_head dhcpv6_leases;
+       struct dhcpv4_lease *dhcpv4_lease;
+       uint32_t ipaddr;
+       uint64_t hostid;
+       size_t mac_count;
+       struct ether_addr *macs;
+       size_t duid_count;
+       struct duid *duids;
+       uint32_t leasetime;             // duration of granted leases, UINT32_MAX = inf
+       char *hostname;
+};
+
 // DNR - RFC9463
 struct dnr_options {
        uint16_t priority;
@@ -487,31 +485,6 @@ enum {
 };
 extern const struct blobmsg_policy lease_cfg_attrs[LEASE_CFG_ATTR_MAX];
 
-inline static void free_assignment(struct dhcp_assignment *a)
-{
-       list_del(&a->head);
-       list_del(&a->lease_cfg_list);
-
-       if (a->dhcp_free_cb)
-               a->dhcp_free_cb(a);
-
-       free(a->hostname);
-       free(a);
-}
-
-inline static struct dhcp_assignment *alloc_assignment(size_t extra_len)
-{
-       struct dhcp_assignment *a = calloc(1, sizeof(*a) + extra_len);
-
-       if (!a)
-               return NULL;
-
-       INIT_LIST_HEAD(&a->head);
-       INIT_LIST_HEAD(&a->lease_cfg_list);
-
-       return a;
-}
-
 inline static bool ra_pio_expired(const struct ra_pio *pio, time_t now)
 {
        return pio->lifetime && (now > pio->lifetime);
@@ -611,8 +584,9 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac
                const struct sockaddr_in6 *addr, const void *data, const uint8_t *end);
 int dhcpv6_ia_init(void);
 int dhcpv6_ia_setup_interface(struct interface *iface, bool enable);
-void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcp_assignment *c, time_t now,
-                               dhcpv6_binding_cb_handler_t func, void *arg);
+void dhcpv6_free_lease(struct dhcpv6_lease *lease);
+void dhcpv6_ia_enum_addrs(struct interface *iface, struct dhcpv6_lease *lease,
+                         time_t now, dhcpv6_binding_cb_handler_t func, void *arg);
 void dhcpv6_ia_write_statefile(void);
 
 int netlink_add_netevent_handler(struct netevent_handler *hdlr);
index f1ce074bbcc5cf0b2f911e50133b7e4f2774799b..4b31e1acd72ce0c2cac08f809bdec5a539734c21 100644 (file)
@@ -120,8 +120,9 @@ static int handle_dhcpv6_leases(_unused struct ubus_context *ctx, _unused struct
                void *i = blobmsg_open_table(&b, iface->ifname);
                void *j = blobmsg_open_array(&b, "leases");
 
-               struct dhcp_assignment *a, *border = list_last_entry(
-                               &iface->ia_assignments, struct dhcp_assignment, head);
+               struct dhcpv6_lease *a, *border;
+
+               border = list_last_entry(&iface->ia_assignments, struct dhcpv6_lease, head);
 
                list_for_each_entry(a, &iface->ia_assignments, head) {
                        if (a == border || (!INFINITE_VALID(a->valid_until) &&